﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;
using SimpleServiceBus.Bus;
using SimpleServiceBus.Bus.Pipeline;
using SimpleServiceBus.Bus.Pipeline.PipelineComponents.MessageLogging;
using SimpleServiceBus.Bus.Transport;
using SimpleServiceBus.Configuration;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoint.Metadata;
using SimpleServiceBus.Messages.Management;

namespace SimpleServiceBus.Tests.Bus.Pipeline.PipelineComponents.MessageLogging
{
    [TestFixture]
    public class MessageLoggerBaseTestFixture
    {
        [Test]
        public void LoggerBaseShouldPrepareLogEntryAndCallProcess()
        {
            //Given
            IMessageContext ctx = GetContext();
            var logger = new TestLogger();

            //When
            logger.LogMessage(ctx, MessageLoggingLevel.HeadersAndBody);

            //Then
            Assert.IsNotNull(logger.Entry);
            Assert.That(logger.Entry.MessageID, Is.EqualTo("testID"));
            Assert.That(logger.Context, Is.SameAs(ctx));
            Assert.That(logger.LogLevel, Is.EqualTo(MessageLoggingLevel.HeadersAndBody));
        }

        [Test]
        public void LoggerBaseShouldSkipHeadersAccordingToLogLevel()
        {
            //Given
            IMessageContext ctx = GetContext();
            var logger = new TestLogger();

            //When
            logger.LogMessage(ctx, MessageLoggingLevel.BodyOnly);

            //Then
            Assert.That(logger.Entry.Headers.Count(), Is.EqualTo(0));
            Assert.That(logger.Entry.Message, Is.EqualTo("testBody"));
        }

        [Test]
        public void LoggerBaseShouldIncludeHeadersAccordingToLogLevel()
        {
            //Given
            IMessageContext ctx = GetContext();
            var logger = new TestLogger();

            //When
            logger.LogMessage(ctx, MessageLoggingLevel.HeadersAndBody);

            //Then
            Assert.That(logger.Entry.Headers.Contains("test = test"));
            Assert.That(logger.Entry.Message, Is.EqualTo("testBody"));
        }

        [Test]
        public void LoggerBaseShouldSkipBodyAccordingToLogLevel()
        {
            //Given
            IMessageContext ctx = GetContext();
            var logger = new TestLogger();

            //When
            logger.LogMessage(ctx, MessageLoggingLevel.HeadersOnly);

            //Then
            Assert.That(logger.Entry.Headers.Contains("test = test"));
            Assert.IsTrue(String.IsNullOrEmpty(logger.Entry.Message as string));
        }

        [Test]
        public void LoggerBaseShouldAllAccordingToLogLevel()
        {
            //Given
            IMessageContext ctx = GetContext();
            var logger = new TestLogger();

            //When
            logger.LogMessage(ctx, MessageLoggingLevel.None);

            //Then
            Assert.IsNull(logger.Entry);
        }

        private static IMessageContext GetContext()
        {
            var message = new MessageEnvelope();
            message.Headers.Add("test", "test");
            message.Body = "testBody";
            message.MessageID = "testID";

            var ctx = MockRepository.GenerateStub<IMessageContext>();
            ctx.Stub(c => c.MessageEnvelope).Return(message);
            return ctx;
        }

        public class TestLogger : MessageLoggerBase
        {
            public MessageLogEntry Entry;
            public IMessageContext Context;
            public MessageLoggingLevel LogLevel;

            protected override void PersistLogEntry(MessageLogEntry logEntry, IMessageContext messageContext, MessageLoggingLevel loggingLevel)
            {
                Entry = logEntry;
                Context = messageContext;
                LogLevel = loggingLevel;
            }
        }
    }
}
